package net.jarang.android.support.http;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.util.EncodingUtil;

public class HttpMethodTemplate {
	public static final String JSON_CONTENT_TYPE = "application/json";

	public static GetMethod getMethod(String uri, Map<String, Object> params, String encoding) {
        GetMethod method = new GetMethod(uri);
        HttpMethodParams httpMethodParams = method.getParams();
        httpMethodParams.setContentCharset(encoding);
        if (params != null) {
        	method.setQueryString(toQueryString(params, encoding));
        }
        return method;
	}
	
	public static GetMethod getMethod(String uri, Map<String, Object> params, Map<String, String> headers, String encoding) {
		GetMethod method = new GetMethod(uri);
		
		HttpMethodParams httpMethodParams = method.getParams();
		httpMethodParams.setContentCharset(encoding);
		
		if (headers != null) {
			httpMethodParams.setCookiePolicy(CookiePolicy.RFC_2109);
			for (Map.Entry<String, String> each : headers.entrySet()) {
				method.setRequestHeader(each.getKey(), each.getValue());
			}
		}
		
		if (params != null) {
			method.setQueryString(toQueryString(params, encoding));
		}
		return method;
	}
	
	public static PostMethod postMethod(String uri, Map<String, Object> params, String encoding) {
        PostMethod method = new PostMethod(uri);
        method.getParams().setContentCharset(encoding);
		if (params != null) {
			for (Entry<String, Object> entry : params.entrySet()) {
				method.addParameter(entry.getKey(), entry.getValue() + "");
			}
		}
        return method;
	}
	
	public static PostMethod postMethod(String uri, Map<String, Object> params, Map<String, String> headers, String encoding) {
		PostMethod method = new PostMethod(uri);
		method.addRequestHeader("content-type", "application/x-www-form-urlencoded");
		
		HttpMethodParams httpMethodParams = method.getParams();
		httpMethodParams.setContentCharset(encoding);
		
		if (headers != null) {
			for (Map.Entry<String, String> each : headers.entrySet()) {
				method.setRequestHeader(each.getKey(), each.getValue());
			}
		}
		
		if (params != null) {
			for (Entry<String, Object> entry : params.entrySet()) {
				method.addParameter(entry.getKey(), entry.getValue() + "");
			}
		}
		return method;
	}
	
	public static PostMethod postMethodForMultipart(String uri, Map<String, Object> params, String encoding) {
		try {
			PostMethod method = new PostMethod(uri);
			method.getParams().setContentCharset(encoding);
			method.setRequestEntity(new MultipartRequestEntity(toParts(params, encoding), method.getParams()));
			return method;
		} catch (Exception e) {
			throw new IllegalArgumentException("PostMethod by Multipart create error!", e);
		}
	}	
	
//	public static PostMethod postMethodByJson(String uri, String encoding, Object...params) {
//		try {
//			PostMethod method = new PostMethod(uri);
//			JSONBuilder builder = new JSONBuilder(params);
//			RequestEntity request = new StringRequestEntity(builder.build(), JSON_CONTENT_TYPE, encoding);
//			method.setRequestEntity(request);
//			return method;
//		} catch (Exception e) {
//			throw new IllegalArgumentException("PostMethod by Json create error!");
//		}
//	}	
	
	static String toQueryString(Map<String, Object> params, String encoding) {
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        for (Entry<String, Object> each : params.entrySet()) {
        	pairs.add(new NameValuePair(each.getKey(), each.getValue() + ""));
        }
        return EncodingUtil.formUrlEncode(pairs.toArray(new NameValuePair[pairs.size()]), encoding);
	}
	
	static Part[] toParts(Map<String, Object> params, String encoding) throws FileNotFoundException {
		List<Part> parts = new ArrayList<Part>();
		if (params != null) {
			for (Entry<String, Object> each : params.entrySet()) {
				Object object = each.getValue();
				if (object instanceof File) {
					parts.add(new FilePart(each.getKey(), (File)object, null, encoding));
				} else {
					parts.add(new StringPart(each.getKey(), each.getValue() + "", encoding));
				}
			}
        }
		return parts.toArray(new Part[parts.size()]);
	}
}
